package com.youlu.campus.service.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youlu.campus.base.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import net.polyv.live.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 *
 */
@Slf4j
public class HttpClientUtils {

    public static HttpResponse post(String url, Object body,String accessToken) throws ClientProtocolException ,IOException {
        return post(url, body, accessToken,null);
    }

    public static HttpResponse postFormData(String url, Map<String,String> params) throws ClientProtocolException ,IOException {
        return postForm(url, params,null);
    }

    public static HttpResponse post(String url, Object body,String accessToken,Cookie... cookies) throws ClientProtocolException ,IOException{
        log.debug("POST请求URL: {}", url);
        HttpResponse response = null;
        CloseableHttpClient client = null;
        try {
            client = HttpClientBuilder.create().build();
            HttpPost request = new HttpPost(url);
            if (Objects.isNull(body)) {
                throw new BusinessException("请求体不能为空");
            }
            log.info("POST发送出消息体: {}", body);
            String str = JSON.toJSONString(body);

            HttpEntity entity = new StringEntity(str, "UTF-8");
            request.setEntity(entity);
            setCookie(request, cookies);
            setRequestId(request);
            request.setHeader(new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()));
            if(StringUtils.isNotBlank(accessToken)){
                request.setHeader("access_token",accessToken);
            }
            response = client.execute(request);
            return response;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            log.error("HttpClient请求错误:{}", e.getLocalizedMessage());
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
            log.error("HttpClient请求错误:{}", e.getLocalizedMessage());
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("HttpClient请求错误:{}", e.getLocalizedMessage());
            throw e;
        } finally {
//            if (Objects.nonNull(client)) {
//                try {
//                    client.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                    log.error("关闭HttpClient错误:{}", e.getLocalizedMessage());
//                }
//            }
//            if (Objects.nonNull(response)) {
//                try {
//                    ((CloseableHttpResponse) response).close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                    log.error("关闭HttpResponse错误:{}", e.getLocalizedMessage());
//                }
//            }
        }
    }


    public static HttpResponse postForm(String url, Map<String,String> params,Cookie... cookies) throws ClientProtocolException ,IOException{
//        log.info("POST请求URL: {},参数：{}", url, JsonUtil.toJSON(params));
        HttpResponse response = null;
        CloseableHttpClient client = null;
        ArrayList<BasicNameValuePair> list = new ArrayList<>();
        params.forEach((key, value) -> list.add(new BasicNameValuePair(key, value)));
        try {
            client = HttpClientBuilder.create().build();
            HttpPost request = new HttpPost(url);

            HttpEntity entity = new UrlEncodedFormEntity(list,Consts.UTF_8);
            request.setEntity(entity);
            setCookie(request, cookies);
            setRequestId(request);
            response = client.execute(request);
            return response;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            log.error("HttpClient请求错误:{}", e.getLocalizedMessage());
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
            log.error("HttpClient请求错误:{}", e.getLocalizedMessage());
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("HttpClient请求错误:{}", e.getLocalizedMessage());
            throw e;
        }
    }

    public static HttpResponse postJsonDataMethod(String url, Object body) throws IOException {
        return postJsonDataMethod(url, body, null);
    }

    public static HttpResponse postJsonDataMethod(String url, Object body, Cookie... cookies) throws IOException {
        log.debug("POST请求URL: {}", url);
        CloseableHttpClient client = HttpClientBuilder.create().build();
        try {
            HttpPost request = new HttpPost(url);
            if (body != null) {
                String str = JSON.toJSONString(body);
                log.info("POST发送出消息体: {}", str);
                HttpEntity entity = new ByteArrayEntity(str.getBytes("UTF-8"));
                request.setEntity(entity);
            }
            setCookie(request, cookies);
            setRequestId(request);
            request.setHeader(new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()));

            HttpResponse response = client.execute(request);
            return response;
        } finally {
        }
    }

    public static HttpResponse postJsonDataAndHeaderMethod(String url, Object body, Map<String, Object> header) throws IOException {
        log.debug("POST请求URL: {}", url);
        CloseableHttpClient client = HttpClientBuilder.create().build();
        try {
            HttpPost request = new HttpPost(url);
            if (body != null) {
                String str = JSON.toJSONString(body);
                log.info("POST发送出消息体: {}", str);
                HttpEntity entity = new ByteArrayEntity(str.getBytes("UTF-8"));
                request.setEntity(entity);
            }
            setRequestId(request);
            request.setHeader(new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()));
            if (header != null) {
                request.setHeader("access_token", header.get("access_token").toString());
            }
            HttpResponse response = client.execute(request);
            return response;
        } finally {
        }
    }

    public static HttpResponse getRequestMethod(String url) throws IOException {
        return getRequestMethod(url, null, null);
    }

    public static HttpResponse getRequestMethod(String url, Map<String, ? extends Object> params, Cookie... cookies) throws IOException {
        log.debug("GET请求URL: {}", url);
        log.debug("GET请求参数： {}", JSON.toJSONString(params));
        CloseableHttpClient client = HttpClientBuilder.create().build();
        try {
            HttpGet request = new HttpGet(url + appendParams(params));
//            setCookie(request, cookies);
//            setRequestId(request);
            HttpResponse response = client.execute(request);
            return response;
        } finally {
        }
    }


    private static void setHeader(HttpRequest request) {

    }

    private static void setRequestId(HttpRequestBase request) {

    }

    private static String appendParams(Map<String, ? extends Object> params) {
        StringBuilder sb = new StringBuilder("?");
        if (params == null || params.size() == 0) {
            return "";
        }
        List<String> strList = new ArrayList<>();
        for (String key : params.keySet()) {
            strList.add(key + "=" + params.get(key).toString());
        }
        String ap = StringUtils.join(strList, "&");
        String result = sb.append(ap).toString();
        log.debug("appendParams result :{}", result);
        return result;
    }

    private static void setCookie(HttpRequest request, Cookie[] cookies) {
        if (cookies != null && cookies.length > 0) {
            List<String> cookieStr = new LinkedList<>();
            for (Cookie cookie : cookies) {
                cookieStr.add(cookie.getName() + "=" + cookie.getValue());
            }
            request.setHeader("Cookie", StringUtils.join(cookieStr, "; "));
        }
    }


    public static String getContent(HttpResponse response) throws IOException {
        HttpEntity responseEntity = response.getEntity();
        StringBuilder sb = new StringBuilder();
        InputStream in = responseEntity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line = "";
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            //log.debug("response inputStream: {}", sb.toString());
            return sb.toString();
        } finally {
            in.close();
        }
    }

    public static JSONObject getContentNoClose(InputStream in) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line = "";
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            log.debug("response inputStream: {}", sb.toString());
            return JSONObject.parseObject(sb.toString());
        } catch (Exception e) {
            return null;
        }
    }

    public static JSONObject httpGet(String url) {
        JSONObject jsonResult = null;
        try {
            HttpResponse response = getRequestMethod(url);
            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
                String strResult = EntityUtils.toString(response.getEntity(), "utf-8");
                /**把json字符串转换成json对象**/
                jsonResult = JSON.parseObject(strResult);
            } else {
                log.error("get请求提交失败:" + url);
            }
        } catch (IOException e) {
            log.error("get请求提交失败:" + url, e);
        }
        return jsonResult;
    }

    /**
     * @param response:HttpResponse
     * @return
     * @throws IOException
     * @throws UnsupportedOperationException
     */
    private static String parseResponseEntity(HttpResponse response) throws IOException, UnsupportedOperationException {
        log.debug("------start parseResponseEntity-------");
        if (response == null || response.getEntity() == null) {
            log.warn("response is null,or entity is null");
            return null;
        }
        InputStream in = null;
        try {
            in = response.getEntity().getContent();
            StringBuilder sb = new StringBuilder();
            byte[] bs = new byte[2048];
            if (in == null) {
                log.error("in is null");
                return null;
            }
            while (in.read(bs) != -1) {
                sb.append(new String(bs).trim());
            }
            log.debug(":>>> end parseResponseEntity-------");
            return sb.toString();

        } catch (IOException iOe) {
//            log.error("IOException,[$errorMsg] is:{}", ExceptionLog.getErrorStack(iOe));
            throw iOe;
        } finally {
            in.close();
            log.debug("close InputStream finished");
        }
    }

    public static RestTemplate getRestTemplate() {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(5000);
        requestFactory.setReadTimeout(5000);
        return new RestTemplate(requestFactory);
    }

    public static RestTemplate getPayRestTemplate() {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(3000);
        requestFactory.setReadTimeout(3000);
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }
}
